package com.pine.app.module.security.oauth.provider.client.dao.impl;

import com.pine.app.module.security.core.common.enums.ErrorType;
import com.pine.app.module.security.oauth.exception.AuthenticationException;
import com.pine.app.module.security.oauth.provider.client.BaseClient;
import com.pine.app.module.security.oauth.provider.client.ClientDetails;
import com.pine.app.module.security.oauth.provider.client.dao.ClientDao;
import com.pine.app.module.security.oauth.provider.client.dao.ScopeDao;
import com.pine.app.module.security.oauth.provider.client.entity.ScopeDetails;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author xiaoyuan
 * @create 2020/3/13 10:36
 **/
@Slf4j
public class ClientDaoImpl implements ClientDao {

    private final JdbcTemplate jdbcTemplate;
    private ScopeDao scopeDao;
    private static final String selectClientDetailsSql = "select client_id, client_secret, client_name," +
            "resources, grant_types, redirect_uri, roles, access_token_validity, refresh_token_validity," +
            " additional_information, autoapprove,expired_time from oauth_client_details where client_id = ? and delete_flag=?";

    public ClientDaoImpl(DataSource dataSource){
        this.jdbcTemplate = new JdbcTemplate(dataSource);
        this.scopeDao = new ScopeDaoImpl(dataSource);
    }

    @Override
    public ClientDetails getClientDetail(String clientId) {
        try {
            BaseClient details = this.jdbcTemplate.queryForObject(this.selectClientDetailsSql, (arg0, arg1) -> {
                BaseClient client = new BaseClient();
                client.setClientId(arg0.getString("client_id"));
                client.setClientName(arg0.getString("client_name"));
                client.setClientSecret(arg0.getString("client_secret"));
                String redirect_uri = arg0.getString("redirect_uri");
                if (!StringUtils.isEmpty(redirect_uri)) {
                    client.setRegisteredRedirectUris(new HashSet<>(Arrays.asList(redirect_uri.split(","))));
                }
                String resources = arg0.getString("resources");
                if (!StringUtils.isEmpty(resources)) {
                    client.setResources(new HashSet<>(Arrays.asList(resources.split(","))));
                }
                String roles = arg0.getString("roles");
                if (!StringUtils.isEmpty(roles)) {
                    client.setRoles(new HashSet<>(Arrays.asList(roles.split(","))));
                }
                String grant_types = arg0.getString("grant_types");
                if (!StringUtils.isEmpty(grant_types)) {
                    client.setAuthorizedGrantTypes(new HashSet<>(Arrays.asList(grant_types.split(","))));
                }
                client.setAccessTokenValiditySeconds(arg0.getInt("access_token_validity"));
                client.setRefreshTokenValiditySeconds(arg0.getInt("refresh_token_validity"));
                client.setExpiredTime(arg0.getLong("expired_time"));
                return client;
            }, new Object[]{clientId,0});
            if (details != null) {
                List<ScopeDetails> scopeDetails = scopeDao.getListByClientId(clientId);
                if (!CollectionUtils.isEmpty(scopeDetails)) {
                    details.setScope(new HashSet<>(scopeDetails.stream().map(ScopeDetails::getScope).collect(Collectors.toList())));
                }
            }
            return details;
        } catch (EmptyResultDataAccessException var4) {
            ErrorType.ILLEGAL_CLIENT_ID.throwThis(AuthenticationException::new);
        }
        return null;
    }

}
